// by Xeno
// Commented/Edited by Tyrghen

//#define __DEBUG__
			
#define __patternpos \
_angle = floor (random 360);\
_x1 = (_current_target_pos select 0) - ((random _radius) * sin _angle);\
_y1 = (_current_target_pos select 1) - ((random _radius) * cos _angle);\
_pat_pos = [_x1, _y1,(_current_target_pos select 2)]

private ["_sleep","_type", "_number", "_target_pos","_current_radius", "_pos", "_town_location","_wait_counter", "_pilot", "_town_name", "_wp_behave", "_heli_type", "_vehicle", "_initial_type", "_grp", "_vehicles", "_funits", "_unit", "_num_p", "_re_random", "_grpskill", "_numair", "_xxx", "_vec_array", "_old_target", "_loop_do", "_dummy", "_current_target_pos", "_wp", "_pat_pos", "_radius", "_old_pat_pos", "_angle", "_x1", "_y1", "_vehicles_number", "_i", "_vecx", "_vec"];
if (!isServer) exitWith {};

_type = _this select 0;
_number = _this select 1;

_wp_behave = "AWARE";

if (isNil "d_addToClean") then {
	d_addToClean = {
		private "_vec";
		_vec = _this select 0;
		d_allunits_add set [count d_allunits_add, _vec];
		if (d_LockAir == 0) then {_vec lock true};
	};
};
diag_log Format["(%1)[%2]: %3",diag_tickTime,"airki.sqf","Script started"];

_initial_type = _type;

while {true} do {
	_grp = objNull;
	_vehicle = objNull;
	_vehicles = [];
	_funits = [];
	_unit = objNull;
	_current_radius = 100;
	_num_p = call XPlayersNumber;
#ifdef __DEBUG__	
d_airki_respawntime= 60;
#endif

	If (AIR_SPAWN_RATIO < 0) then {
		_num_p = call XPlayersNumber;
		AIR_SPAWN_RATIO = switch (true) do {
			case (_num_p < 5): {0.5};
			case (_num_p < 8): {0.7};
			default {1};
		};
	};
	_air_spawn_ratio = AIR_SPAWN_RATIO;
	
	_sleep = (switch (true) do {
		case (_num_p < 5): {d_airki_respawntime/4};
		case (_num_p < 10): {d_airki_respawntime/6};
		case (_num_p < 20): {d_airki_respawntime/8};
		default {0};
	});
	if (_air_spawn_ratio >0) then {_sleep = (_sleep / _air_spawn_ratio);};
	sleep _sleep;
	
	_pos = call XfGetRanPointOuterAir;
	while {_pos distance FLAG_BASE < 1000} do {
		_pos = call XfGetRanPointOuterAir;
		sleep 0.01;
	};
	_grpskill = 0.6 + (random 0.3);
	// 50% of the time we'll send a light MI rather than a SU... what a relief :)
	if (_initial_type == "SU") then {_type = (if ((random 100) > 50) then {"MIMG"} else {"SU"})};
	
	_grp = [d_side_enemy] call x_creategroup;
	_heli_type = "";
	_numair = 0;
	_num_p = (call XPlayersNumber * 0.1);
	switch (_type) do {
		case "KA": {
			_heli_type = d_airki_attack_chopper call XfRandomArrayVal;
			_numair = round(d_number_attack_choppers * (_num_p min 3));
		};
		case "SU": {
			_heli_type = d_airki_attack_plane call XfRandomArrayVal;
			_numair = round(d_number_attack_planes * (_num_p min 3));
		};
		case "MIMG": {
			_heli_type = d_light_attack_chopper call XfRandomArrayVal;
			_numair = round(d_number_attack_choppers * (_num_p min 3));
		};
	};
	_numair = floor(_numair);
	If (_numair <= 0) then {_numair = 1;};
	// The goal here is for low players numbers to have less aerial spawn. Because it makes otherwise everything way harder :)
	if (_air_spawn_ratio < 1) then {
		If (_air_spawn_ratio <= random(1)) then {
#ifdef __DEBUG__	
diag_log Format["(%1)[%2]: %3: %4 (%5)",diag_tickTime,"airki.sqf","Air Spawn Canceled", _numair, _air_spawn_ratio];
#endif
			_numair = 0; 
		};
	};
	// And here they wanted it hellish :)
	if (_air_spawn_ratio > 1) then {
		_numair = floor(_numair * _air_spawn_ratio);
	};
#ifdef __DEBUG__	
diag_log Format["(%1)[%2]: %3: %4 (%5)",diag_tickTime,"airki.sqf","Num Air", _numair, _air_spawn_ratio];
#endif
	
	If (WithAirKiSpawn And (_numair > 0)) then {
		_cdir = [_pos, d_island_center] call XfDirTo;
		// We get a number of air vehicles between 1 and the max number to create.
		If (_numair > 1) then {	_numair = 1 + round(random (_numair - 1));};
#ifdef __DEBUG__	
_marker_name = Format["ki%1%2",_type,ceil(random 10)];
[_marker_name, [0,0,0],"ICON","ColorRed",[2,2],"Target",0,"o_unknown"] call XfCreateMarkerGlobal;
diag_log Format["(%1)[%2]: %3: %4 (%5)",diag_tickTime,"airki.sqf","Randomized Num Air", _numair, _air_spawn_ratio];
#endif
		// We instantiate all units and add them to the group.
		_grp setFormation "VEE";
		_grp setBehaviour "CARELESS";
		_grp setCombatMode "RED";
		_grp setSpeedMode "FULL";
		for "_xxx" from 1 to _numair do {
			_vec_array = [[_pos select 0, _pos select 1, 400], _cdir, _heli_type, _grp] call XfSpawnVehicle;
			_vehicle = _vec_array select 0;
			_vehicle setPos [_pos select 0, _pos select 1, 400];
			_vehicles set [count _vehicles, _vehicle];
			_funits = [_funits, (_vec_array select 1)] call XfArrayPushStack;
			[_vehicle] call d_addToClean;
			_vehicle flyInHeight 200;
			If (_type == "SU") then { _vehicle flyInHeight 400; };
			_vehicle spawn XfAirMarkerMove;
			sleep 0.1;
#ifdef __DEBUG__
diag_log Format["(%1)[%2]: %3: type:%4  grp:%5  driver:%6  crew:%7",diag_tickTime,"airki.sqf","Spawned vehicle",typeof _vehicle, _grp, str(driver _vehicle), count(crew _vehicle)];
#endif
		};
		(leader _grp) setSkill _grpskill;
		sleep 1.011;
		_grp allowFleeing 0;
		
		_loop_do = true;
		
		// We load either the current target position set in the mission
		// or we load one of the towns randomly.
		_target_pos = (["current_mission_position", [[0,0,0],0]] call XNetGetJIP) select 0;
		if ((Format["%1",_target_pos] == "[0,0,0]") OR (Format["%1",_target_pos] == "[]")) then {
			// _town_location = d_town_markers call XfRandomArrayVal;
			_town_location = d_all_markers call XfRandomArrayVal;
			_current_target_pos = _town_location select 0;
			_town_name = _town_location select 1;
			_current_radius = _town_location select 2;
		} else {
			_current_target_pos = _target_pos;
			_current_radius = (["current_mission_position", [[0,0,0],300]] call XNetGetJIP) select 1;
			_town_name = "Mission";
		};
#ifdef __DEBUG__
diag_log Format["(%1)[%2]: 1) %3 heading to %4 at %5 (%6)",diag_tickTime,"airki.sqf",typeof _vehicle,_town_name,_current_target_pos, getpos _vehicle];
#endif
		
		_wp = _grp addWayPoint [_current_target_pos, 0];
		_wp setWaypointType "SAD";
		_pat_pos = _current_target_pos;
		_wait_counter = 0;
		[_grp, 1] setWaypointStatements ["never", ""];
#ifdef __DEBUG__
_marker_name setMarkerPos _current_target_pos;
_marker_name setMarkerText "Current Target";
#endif
		_last_wp_pos = [0,0,0];
		while {_loop_do} do {
			// We take the first vehicle in the list. If one is destroyed, there will always be a first one.
			_vehicle = _vehicles select 0;
			_pilot = driver _vehicle;
			If ((behaviour _pilot) == "COMBAT") then { _wait_counter = 0 };
			// Calculate the radius which sets when the destination is reached
			sleep 3 + random 2;
			_radius = switch (_type) do {
				case "KA": {_current_radius * 3};
				case "MIMG": {_current_radius * 3};
				case "SU": {_current_radius * 5};
				default {_current_radius};
			};

			// Set the current target position.
			// If we have a global position set for the current mission target, all units will go there.
			// If not, then a random town is picked. They wait there a bit, then go away to the next.
			_target_pos = (["current_mission_position", [[0,0,0],300]] call XNetGetJIP) select 0;
			if ((Format["%1",_target_pos] == "[0,0,0]") OR (Format["%1",_target_pos] == "[]")) then {
				// If we didn't have a town location, we get one.
				if (isNil "_town_location") then {
					// _town_location = d_town_markers call XfRandomArrayVal;
					_town_location = d_all_markers call XfRandomArrayVal;
					_wait_counter = 0;
					_grp setSpeedMode "NORMAL";
					_grp setBehaviour "AWARE";
#ifdef __DEBUG__
diag_log Format["(%1)[%2]: %3 heading to %4 at %5 (%6)",diag_tickTime,"airki.sqf",typeof _vehicle,_town_name,_current_target_pos, getpos _vehicle];
#endif
				};
				If (_wait_counter > 8) then {
					while {(_town_name == (_town_location select 1)) Or (isNil "_town_name") } do {
						// _town_location = d_town_markers call XfRandomArrayVal;
						_town_location = d_all_markers call XfRandomArrayVal;
					};
					_wait_counter = 0;
					_grp setSpeedMode "NORMAL";
					_grp setBehaviour "AWARE";
				};
				_current_target_pos = _town_location select 0;
				_town_name = _town_location select 1;
				_current_radius = _town_location select 2;
			} else {
				_current_target_pos = _target_pos;
				_town_location = objNull;
				_town_name = "Mission";
				_wait_counter = 0;
				_current_radius = (["current_mission_position", [[0,0,0],300]] call XNetGetJIP) select 1;
			};

			if (_vehicle distance _current_target_pos < _radius) then {
				if (_type == "KA" || _type == "MIMG") then {
					If (_type == "SU") then { _vehicle flyInHeight 200; };
					_old_pat_pos = _pat_pos;
					__patternpos;
					while {_pat_pos distance _old_pat_pos < 100} do {
						__patternpos;
						sleep 0.01;
					};
					_pat_pos = _pat_pos call XfWorldBoundsCheck;
					[_grp, 1] setWaypointPosition [_pat_pos, 0];
					_grp setSpeedMode "NORMAL";
					_grp setBehaviour _wp_behave;
#ifdef __DEBUG__
_marker_name setMarkerPos _pat_pos;
_marker_name setMarkerText "Pattern Target";
#endif
					sleep 45.821 + random 15;
				} else {
					__patternpos;
					_pat_pos = _pat_pos call XfWorldBoundsCheck;
					[_grp, 1] setWaypointPosition [_pat_pos, 0];
					_grp setSpeedMode "LIMITED";
					_grp setBehaviour _wp_behave;
#ifdef __DEBUG__
_marker_name setMarkerPos _pat_pos;
_marker_name setMarkerText "Pattern Target";
#endif
					sleep 60 + random 20;
				};
				_wait_counter = _wait_counter + 1;
			} else {
				// We update the way point in case it changed.
				If (Format["%1",_last_wp_pos] != Format["%1",_current_target_pos]) then {
					[_grp, 1] setWaypointPosition [_current_target_pos, 0];
					_last_wp_pos = _current_target_pos;
#ifdef __DEBUG__
diag_log Format["(%1)[%2]: %3 heading to %4 at %5 (%6, %7)",diag_tickTime,"airki.sqf",typeof _vehicle,_town_name,_current_target_pos, getpos _vehicle,_vehicle distance _current_target_pos];
#endif
				};
#ifdef __DEBUG__
_marker_name setMarkerPos _current_target_pos;
_marker_name setMarkerText "Current Target";
#endif
				If (_type == "SU") then { _vehicle flyInHeight 400; };
			};

			// This part will refuel the vehicle or delete it if destroyed
			if (count _vehicles > 0) then {
				_vehicles_number = count _vehicles;
				for "_i" from 0 to _vehicles_number do {
					_vecx = _vehicles select _i;
					if (fuel _vecx < 0.1 && canMove _vecx) then {
#ifdef __DEBUG__
diag_log Format["(%1)[%2]: %3 (%4)",diag_tickTime,"airki.sqf","Vehicle out of fuel", typeof(_vecx) ];
#endif
						_vecx spawn {
							private "_vec";
							_vec = _this;
							_vec setDamage 1.1;
							sleep 200;
							if (!isNull _vec) then {_vec call XfDelVecAndCrew};
						};
						_vehicles set [_i, -1];
					} else {
						if (isNull _vecx || !alive _vecx || !canMove _vecx) then {
							_vehicles set [_i, -1];
#ifdef __DEBUG__
diag_log Format["(%1)[%2]: %3 (%4)",diag_tickTime,"airki.sqf","Deleted vehicle", typeof(_vecx) ];
#endif
						} else {
							_vecx setFuel 1;
						};
					};
					sleep 0.01;
				};
				_vehicles = _vehicles - [-1];
			};
			if (count _vehicles == 0) then {
				{if (!isNull _x) then {_x setDamage 1; sleep 0.01; deleteVehicle _x}} forEach _funits;
#ifdef __DEBUG__
diag_log Format["(%1)[%2]: %3",diag_tickTime,"airki.sqf","All vehicles destroyed"];
#endif
				_funits = [];
				_vehicles = [];
				_loop_do = false;
			};
		};
#ifdef __DEBUG__
// We exited, this means that the vehicle is destroyed or else
_marker_name setMarkerPos [0,0,0];
_marker_name setMarkerText "";
deleteMarkerLocal _marker_name;
#endif
	} else {
		diag_log Format["(%1)[%2]: %3 (%4)",diag_tickTime,"airki.sqf","Not enough players or coeffs too low to generate a unit",_numair];
	};
	_num_p = call XPlayersNumber;
	_re_random = switch (true) do {
		case (_num_p < 5): {d_airki_respawntime};
		case (_num_p < 10): {d_airki_respawntime / 2};
		case (_num_p < 20): {d_airki_respawntime /3.5};
		default {d_airki_respawntime / 4};
	};
	sleep (_re_random + random (_re_random));
};
